package jspeakserver;

import modelo.Mensaje;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author Manuel Figueroa Recio
 */
public class HiloServidor implements Runnable {
    private boolean listo = true; // indica si esta listo para enviar o esta siendo utilizado.
    private Mensaje mensaje ; // mensaje a recibir
    public Cliente cliente; // enlace con cliente
    private Thread hilo;     // hilo de escucha
    private boolean escuchando = true; // para el bucle
    private ObjectInputStream entrada;
    private ObjectOutputStream salida;
    private Socket socket;
    private Pila pila;

    public HiloServidor(Cliente cliente,ObjectInputStream entrada, ObjectOutputStream salida,Socket socket,Pila pila){
        this.cliente = cliente;
        this.entrada = entrada;
        this.salida = salida;
        this.socket = socket;
        this.pila = pila;
    }

    public void iniciar(){
        hilo = new Thread(this);
        hilo.start();
    }

    public void run() {
        while(escuchando){
            try {
                System.out.println("Escuchando mensajes");
                mensaje = (Mensaje) entrada.readObject();
                System.out.println("Mensaje capturado:");
                System.out.println(mensaje.getMensaje());
                if (!mensaje.getTipo().equalsIgnoreCase("sistema")){ // mensaje distinto de sistema
                    System.out.println("preparando mensaje");
                    prepararMensaje(mensaje);
                }
                else{

                }
            } catch (Exception ex) {
                System.out.println("El cliente" + getCliente().getNombre() + " se ha desconectado;");
                finalizar();
            }
        }
    }

    /**
     * Prepara y el mensaje msj dependiendo del tipo y luego utiliza enviarMensaje para remitirlos
     * @param msj el mensaje a preparar
     */
    
    public void prepararMensaje(Mensaje msj){
        Cliente tempClient;
            if(msj.getTipo().equalsIgnoreCase("broadcast")){ //comprueba si es multicast
                for(int i=0;i<pila.getNumHilos();i++){
                    pila.getHilo(i).enviarMensaje(msj);
                }
            }
            else{
               if (msj.getTipo().equalsIgnoreCase("unicast")) {
                   // Pilla el cliente segun el nombre y manda el mensaje
                    pila.getHilo(msj.getDestino()).enviarMensaje(msj);
                    

               }
            }
    }


    /**
     * Envia el mensaje a su cliente asociado.
     * Implementa sistema para gestionar el acceso.
     * @param msj
     */
    public synchronized void enviarMensaje(Mensaje msj){
            while (!listo) {
                try {
                    wait();
                    System.out.println("En espera");
                } catch (InterruptedException ex) {
                    Logger.getLogger(HiloServidor.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        try {
        listo = false; //marcamos que esta ocupado.

        salida.writeObject(msj);
        salida.flush();

        } catch (IOException ex) {
            Logger.getLogger(HiloServidor.class.getName()).log(Level.SEVERE, null, ex);
            // auditoria error mensaje no se pudo enviar
        }

        listo = true;
        notify();

    }

    public void finalizar(){
        escuchando = false;
        pila.removeHilo(this);
        entrada = null;
        salida = null;
        cliente = null;
        if (socket.isConnected()){
            try {
                socket.close();
            } catch (IOException ex) {
                socket = null;
            }
        }
    }

    /**
     * @return the cliente
     */
    public Cliente getCliente() {
        return cliente;
    }

    /**
     * @param cliente the cliente to set
     */
    public void setCliente(Cliente cliente) {
        this.cliente = cliente;
    }


}
